<!DOCTYPE html>

<html>
<head>
  <title>repl.coffee</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page_wrapper">
            <div id="jump_page">
              
                
                <a class="source" href="browser.html">
                  browser.coffee
                </a>
              
                
                <a class="source" href="cake.html">
                  cake.coffee
                </a>
              
                
                <a class="source" href="coffee-script.html">
                  coffee-script.coffee
                </a>
              
                
                <a class="source" href="command.html">
                  command.coffee
                </a>
              
                
                <a class="source" href="grammar.html">
                  grammar.coffee
                </a>
              
                
                <a class="source" href="helpers.html">
                  helpers.coffee
                </a>
              
                
                <a class="source" href="index.html">
                  index.coffee
                </a>
              
                
                <a class="source" href="lexer.html">
                  lexer.coffee
                </a>
              
                
                <a class="source" href="nodes.html">
                  nodes.coffee
                </a>
              
                
                <a class="source" href="optparse.html">
                  optparse.coffee
                </a>
              
                
                <a class="source" href="register.html">
                  register.coffee
                </a>
              
                
                <a class="source" href="repl.html">
                  repl.coffee
                </a>
              
                
                <a class="source" href="rewriter.html">
                  rewriter.coffee
                </a>
              
                
                <a class="source" href="scope.html">
                  scope.litcoffee
                </a>
              
                
                <a class="source" href="sourcemap.html">
                  sourcemap.litcoffee
                </a>
              
            </div>
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>repl.coffee</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffee-script'</span>
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>

replDefaults =
  <span class="hljs-attribute">prompt</span>: <span class="hljs-string">'coffee&gt; '</span>,
  <span class="hljs-attribute">historyFile</span>: path.join process.env.HOME, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> process.env.HOME
  <span class="hljs-attribute">historyMaxInputSize</span>: <span class="hljs-number">10240</span>
  <span class="hljs-attribute">eval</span>: <span class="hljs-function"><span class="hljs-params">(input, context, filename, cb)</span> -&gt;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>XXX: multiline hack.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    input = input.replace <span class="hljs-regexp">/\uFF00/g</span>, <span class="hljs-string">'\n'</span></pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>Node’s REPL sends the input ending with a newline and then wrapped in
parens. Unwrap all that.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    input = input.replace <span class="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>Require AST nodes to do some AST manipulation.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    {Block, Assign, Value, Literal} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>

    <span class="hljs-keyword">try</span></pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>Tokenize the clean input.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      tokens = CoffeeScript.tokens input</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      referencedVars = (
        token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.variable
      )</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>Generate the AST of the tokens.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      ast = CoffeeScript.nodes tokens</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>Add assignment to <code>_</code> variable to force the input to be an expression.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      ast = <span class="hljs-keyword">new</span> Block [
        <span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'_'</span>), ast, <span class="hljs-string">'='</span>
      ]
      js = ast.compile {<span class="hljs-attribute">bare</span>: <span class="hljs-literal">yes</span>, <span class="hljs-attribute">locals</span>: Object.keys(context), referencedVars}
      result = <span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
        vm.runInThisContext js, filename
      <span class="hljs-keyword">else</span>
        vm.runInContext js, context, filename
      cb <span class="hljs-literal">null</span>, result
    <span class="hljs-keyword">catch</span> err</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>AST’s <code>compile</code> does not add source code information to syntax errors.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      updateSyntaxError err, input
      cb err

<span class="hljs-function"><span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -&gt;</span>
  {rli, inputStream, outputStream} = repl</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>Node 0.11.12 changed API, prompt is now _prompt.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  origPrompt = repl._prompt ? repl.prompt

  multiline =
    <span class="hljs-attribute">enabled</span>: <span class="hljs-literal">off</span>
    <span class="hljs-attribute">initialPrompt</span>: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
    <span class="hljs-attribute">prompt</span>: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*&gt;?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
    <span class="hljs-attribute">buffer</span>: <span class="hljs-string">''</span></pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>Proxy node’s line listener</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
  rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
  rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -&gt;</span>
    <span class="hljs-keyword">if</span> multiline.enabled
      multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
      rli.setPrompt multiline.prompt
      rli.prompt <span class="hljs-literal">true</span>
    <span class="hljs-keyword">else</span>
      rli.setPrompt origPrompt
      nodeLineListener cmd
    <span class="hljs-keyword">return</span></pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <p>Handle Ctrl-v</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">'keypress'</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -&gt;</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">'v'</span>
    <span class="hljs-keyword">if</span> multiline.enabled</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>allow arbitrarily switching between modes any time before multiple lines are entered</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
        multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
        rli.setPrompt origPrompt
        rli.prompt <span class="hljs-literal">true</span>
        <span class="hljs-keyword">return</span></pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              <p>no-op unless the current line is empty</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> rli.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> rli.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>eval, print, loop</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
      rli.line = <span class="hljs-string">''</span>
      rli.cursor = <span class="hljs-number">0</span>
      rli.output.cursorTo <span class="hljs-number">0</span>
      rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <p>XXX: multiline hack</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
      rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
      multiline.buffer = <span class="hljs-string">''</span>
    <span class="hljs-keyword">else</span>
      multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
      rli.setPrompt multiline.initialPrompt
      rli.prompt <span class="hljs-literal">true</span>
    <span class="hljs-keyword">return</span></pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              <p>Store and load command history from a file</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">addHistory</span> = <span class="hljs-params">(repl, filename, maxSize)</span> -&gt;</span>
  lastLine = <span class="hljs-literal">null</span>
  <span class="hljs-keyword">try</span></pre></div></div>
            
        </li>
        
        
        <li id="section-18">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-18">&#182;</a>
              </div>
              <p>Get file info and at most maxSize of command history</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    stat = fs.statSync filename
    size = Math.min maxSize, stat.size</pre></div></div>
            
        </li>
        
        
        <li id="section-19">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-19">&#182;</a>
              </div>
              <p>Read last <code>size</code> bytes from the file</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
    buffer = <span class="hljs-keyword">new</span> Buffer(size)
    fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-20">&#182;</a>
              </div>
              <p>Set the history on the interpreter</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-21">&#182;</a>
              </div>
              <p>If the history file was truncated we should pop off a potential partial line</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size &gt; maxSize</pre></div></div>
            
        </li>
        
        
        <li id="section-22">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-22">&#182;</a>
              </div>
              <p>Shift off the final blank newline</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    repl.rli.history.shift() <span class="hljs-keyword">if</span> repl.rli.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
    repl.rli.historyIndex = -<span class="hljs-number">1</span>
    lastLine = repl.rli.history[<span class="hljs-number">0</span>]

  fd = fs.openSync filename, <span class="hljs-string">'a'</span>

  repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
    <span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
            
        </li>
        
        
        <li id="section-23">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-23">&#182;</a>
              </div>
              <p>Save the latest command in the file</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      fs.write fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
      lastLine = code

  repl.rli.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>,<span class="hljs-function"> -&gt;</span> fs.close fd</pre></div></div>
            
        </li>
        
        
        <li id="section-24">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-24">&#182;</a>
              </div>
              <p>Add a command to show the history stack</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
    <span class="hljs-attribute">help</span>: <span class="hljs-string">'Show command history'</span>
    <span class="hljs-attribute">action</span>:<span class="hljs-function"> -&gt;</span>
      repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.rli.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
      repl.displayPrompt()

<span class="hljs-function"><span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -&gt;</span></pre></div></div>
            
        </li>
        
        
        <li id="section-25">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-25">&#182;</a>
              </div>
              <p>Node 0.11 changed API, a command such as ‘.help’ is now stored as ‘help’</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>  commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
  <span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">".<span class="hljs-subst">#{commandName}</span>"</span> <span class="hljs-keyword">else</span> commandName

<span class="hljs-built_in">module</span>.<span class="hljs-built_in">exports</span> =
  <span class="hljs-attribute">start</span>: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -&gt;</span>
    [major, minor, build] = process.versions.node.split<span class="hljs-function"><span class="hljs-params">(<span class="hljs-string">'.'</span>)</span>.<span class="hljs-title">map</span> <span class="hljs-params">(n)</span> -&gt;</span> parseInt(n)

    <span class="hljs-keyword">if</span> major <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> minor &lt; <span class="hljs-number">8</span>
      <span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 0.8.0+ required for CoffeeScript REPL"</span>
      process.exit <span class="hljs-number">1</span>

    CoffeeScript.register()
    process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
    opts = merge replDefaults, opts
    repl = nodeREPL.start opts
    repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>,<span class="hljs-function"> -&gt;</span> repl.outputStream.write <span class="hljs-string">'\n'</span>
    addMultilineHandler repl
    addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-26">&#182;</a>
              </div>
              <p>Adapt help inherited from the node REPL</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    repl.commands[getCommandId(repl, <span class="hljs-string">'load'</span>)].help = <span class="hljs-string">'Load code from a file into this REPL session'</span>
    repl</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
